home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / config.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  14KB  |  521 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: config.c,v 1.90 2001/03/03 19:00:55 drscholl Exp $ */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11. #include <limits.h>
  12. #include <errno.h>
  13. #include "opennap.h"
  14. #include "debug.h"
  15.  
  16. typedef enum
  17. {
  18.     VAR_TYPE_INT,
  19.     VAR_TYPE_STR,
  20.     VAR_TYPE_BOOL,
  21.     VAR_TYPE_LIST
  22. }
  23. VAR_TYPE;
  24.  
  25. #define CF_ONCE    1        /* may only be set in config file or command line */
  26.  
  27. struct config
  28. {
  29.     char   *name;
  30.     VAR_TYPE type;
  31.     unsigned long val;
  32.     unsigned long def;        /* default value */
  33.     u_int   flags;
  34. };
  35.  
  36. #define UL (unsigned long)
  37.  
  38. static struct config Vars[] = {
  39. #ifndef ROUTING_ONLY
  40.     {"file_count_threshold", VAR_TYPE_INT, UL & File_Count_Threshold, 5000,
  41.      0},
  42.     {"max_results", VAR_TYPE_INT, UL & Max_Search_Results, 100, 0},
  43.     {"max_shared", VAR_TYPE_INT, UL & Max_Shared, 5000, 0},
  44.     {"stats_port", VAR_TYPE_INT, UL & Stats_Port, 8889, CF_ONCE},
  45.     {"max_searches", VAR_TYPE_INT, UL & Max_Searches, 3, 0},
  46.     {"report_name", VAR_TYPE_STR, UL & global.report_name, 0, 0},
  47.     {"report_ip", VAR_TYPE_STR, UL & global.report_ip, 0, 0},
  48.     {"report_port", VAR_TYPE_INT, UL & global.report_port, 0, 0},
  49.     {"stat_server_host", VAR_TYPE_STR, UL & global.stat_server,
  50.      UL "stats.napigator.com", 0},
  51.     {"stat_server_pass", VAR_TYPE_STR, UL & global.stat_pass, UL "", 0},
  52.     {"stat_server_port", VAR_TYPE_INT, UL & global.stat_server_port, 8890, 0},
  53.     {"stat_server_user", VAR_TYPE_STR, UL & global.stat_user, UL "", 0},
  54. #endif
  55.     {"allow_share", VAR_TYPE_BOOL, ON_ALLOW_SHARE, 1, 0},
  56.     {"auto_link", VAR_TYPE_BOOL, ON_AUTO_LINK, 0, 0},
  57.     {"auto_register", VAR_TYPE_BOOL, ON_AUTO_REGISTER, 0, 0},
  58.     {"client_queue_length", VAR_TYPE_INT, UL & Client_Queue_Length, 102400,
  59.      0},
  60.     {"compression_level", VAR_TYPE_INT, UL & Compression_Level, 1, CF_ONCE},
  61.     {"eject_when_full", VAR_TYPE_BOOL, ON_EJECT_WHEN_FULL, 0, 0},
  62.     {"flood_commands", VAR_TYPE_INT, UL & Flood_Commands, 0, 0},
  63.     {"flood_time", VAR_TYPE_INT, UL & Flood_Time, 0, 0},
  64.     {"ghost_kill", VAR_TYPE_BOOL, ON_GHOST_KILL, 1, 0},
  65.     {"irc_channels", VAR_TYPE_BOOL, ON_IRC_CHANNELS, 1, 0},
  66.     {"listen_addr", VAR_TYPE_STR, UL & Listen_Addr, UL "0.0.0.0", CF_ONCE},
  67.     {"log_mode", VAR_TYPE_BOOL, ON_LOGLEVEL_CHANGE, 0, 0},
  68.     {"login_interval", VAR_TYPE_INT, UL & Login_Interval, 0, 0},
  69.     {"login_timeout", VAR_TYPE_INT, UL & Login_Timeout, 60, 0},
  70.     {"max_browse_result", VAR_TYPE_INT, UL & Max_Browse_Result, 500, 0},
  71.     {"max_channel_length", VAR_TYPE_INT, UL & Max_Channel_Length, 32, 0},
  72.     {"max_client_string", VAR_TYPE_INT, UL & Max_Client_String, 32, 0},
  73.     {"max_clones", VAR_TYPE_INT, UL & Max_Clones, 0, 0},
  74.     {"max_command_length", VAR_TYPE_INT, UL & Max_Command_Length, 2048, 0},
  75.     {"max_connections", VAR_TYPE_INT, UL & Max_Connections, FD_SETSIZE, 0},
  76.     {"max_hotlist", VAR_TYPE_INT, UL & Max_Hotlist, 32, 0},
  77.     {"max_ignore", VAR_TYPE_INT, UL & Max_Ignore, 32, 0},
  78.     {"max_nick_length", VAR_TYPE_INT, UL & Max_Nick_Length, 19, 0},
  79.     {"max_reason", VAR_TYPE_INT, UL & Max_Reason, 64, 0},
  80.     {"max_time_delta", VAR_TYPE_INT, UL & Max_Time_Delta, 90, 0},
  81.     {"max_topic", VAR_TYPE_INT, UL & Max_Topic, 64, 0},
  82.     {"max_user_channels", VAR_TYPE_INT, UL & Max_User_Channels, 5, 0},
  83.     {"min_read", VAR_TYPE_INT, UL & global.min_read, 0, 0},
  84.     {"nick_expire", VAR_TYPE_INT, UL & Nick_Expire, 2678400 /* 31 days */ ,
  85.      0},
  86.     {"ping_interval", VAR_TYPE_INT, UL & Ping_Interval, 600, 0},
  87.     {"register_interval", VAR_TYPE_INT, UL & Register_Interval, 0, 0},
  88.     {"registered_only", VAR_TYPE_BOOL, ON_REGISTERED_ONLY, 0, 0},
  89.     {"remote_browse", VAR_TYPE_BOOL, ON_REMOTE_BROWSE, 1, 0},
  90.     {"restrict_registration", VAR_TYPE_BOOL, ON_RESTRICT_REGISTRATION, 0, 0},
  91.     {"search_timeout", VAR_TYPE_INT, UL & Search_Timeout, 180, 0},
  92.     {"server_alias", VAR_TYPE_STR, UL & Server_Alias, 0, CF_ONCE},
  93.     {"server_chunk", VAR_TYPE_INT, UL & Server_Chunk, 0, 0},
  94.     {"server_name", VAR_TYPE_STR, UL & Server_Name, 0, CF_ONCE},
  95.     {"server_ports", VAR_TYPE_LIST, UL & Server_Ports, UL "8888", CF_ONCE},
  96.     {"server_queue_length", VAR_TYPE_INT, UL & Server_Queue_Length, 1048576,
  97.      0},
  98.     {"stat_click", VAR_TYPE_INT, UL & global.stat_click, 60, 0},
  99.     {"strict_channels", VAR_TYPE_BOOL, ON_STRICT_CHANNELS, 0, 0},
  100.     {"user_db_interval", VAR_TYPE_INT, UL & User_Db_Interval, 1800, 0},
  101.     {"usermode", VAR_TYPE_STR, UL & UserMode, UL "ALL", CF_ONCE},
  102.     {"warn_time_delta", VAR_TYPE_INT, UL & Warn_Time_Delta, 30, 0},
  103.     {"who_was_time", VAR_TYPE_INT, UL & Who_Was_Time, 300, 0},
  104. #ifndef WIN32
  105.     {"connection_hard_limit", VAR_TYPE_INT, UL & Connection_Hard_Limit,
  106.      FD_SETSIZE, CF_ONCE},
  107.     {"max_data_size", VAR_TYPE_INT, UL & Max_Data_Size, -1, CF_ONCE},
  108.     {"max_rss_size", VAR_TYPE_INT, UL & Max_Rss_Size, -1, CF_ONCE},
  109.     {"lock_memory", VAR_TYPE_BOOL, ON_LOCK_MEMORY, 0, CF_ONCE},
  110. #endif
  111. };
  112.  
  113. static int Vars_Size = sizeof (Vars) / sizeof (struct config);
  114.  
  115. static void
  116. set_int_var (struct config *v, int val)
  117. {
  118.     ASSERT (v->type == VAR_TYPE_INT);
  119.     *(int *) v->val = val;
  120. }
  121.  
  122. static void
  123. set_str_var (struct config *v, const char *s)
  124. {
  125.     char  **ptr;
  126.  
  127.     ASSERT (v->type == VAR_TYPE_STR);
  128.     ptr = (char **) v->val;
  129.     if (*ptr)
  130.     FREE (*ptr);
  131.     *ptr = STRDUP (s);
  132. }
  133.  
  134. static void
  135. set_list_var (struct config *v, const char *s)
  136. {
  137.     int     ac, i;
  138.     char   *av[32];
  139.     LIST   *tmpList, *list = 0;
  140.  
  141.  
  142.     ASSERT (v->type == VAR_TYPE_LIST);
  143.     strncpy (Buf, s, sizeof (Buf) - 1);
  144.     Buf[sizeof (Buf) - 1] = 0;
  145.     ac = split_line (av, FIELDS (av), Buf);
  146.     for (i = 0; i < ac; i++)
  147.     {
  148.     tmpList = CALLOC (1, sizeof (LIST));
  149.     tmpList->data = STRDUP (av[i]);
  150.     tmpList->next = list;
  151.     list = tmpList;
  152.     }
  153.     list_free (*(LIST **) v->val, free_pointer);
  154.     *(LIST **) v->val = list;
  155. }
  156.  
  157. static void
  158. set_bool_var (struct config *v, int on)
  159. {
  160.     ASSERT (v->type == VAR_TYPE_BOOL);
  161.     if (on)
  162.     Server_Flags |= v->val;
  163.     else
  164.     Server_Flags &= ~v->val;
  165. }
  166.  
  167. static int
  168. set_var (const char *var, const char *val, int init)
  169. {
  170.     int     i, n;
  171.     char   *ptr;
  172.  
  173.     for (i = 0; i < Vars_Size; i++)
  174.     {
  175.     if (!strcmp (Vars[i].name, var))
  176.     {
  177.         if (!init && (Vars[i].flags & CF_ONCE))
  178.         {
  179.         log ("set_var: %s may not be reset/only set in the config file", Vars[i].name);
  180.         return -1;
  181.         }
  182.         if (Vars[i].type == VAR_TYPE_INT)
  183.         {
  184.         n = strtol (val, &ptr, 10);
  185.         if (*ptr)
  186.         {
  187.             log ("set_var: invalid integer value: %s", val);
  188.             return -1;
  189.         }
  190.         set_int_var (&Vars[i], n);
  191.         }
  192.         else if (Vars[i].type == VAR_TYPE_STR)
  193.         set_str_var (&Vars[i], val);
  194.         else if (Vars[i].type == VAR_TYPE_BOOL)
  195.         {
  196.         if (!strcasecmp ("yes", val) || !strcasecmp ("on", val))
  197.             n = 1;
  198.         else if (!strcasecmp ("no", val) || !strcasecmp ("off", val))
  199.             n = 0;
  200.         else
  201.         {
  202.             n = strtol (val, &ptr, 10);
  203.             if (*ptr)
  204.             {
  205.             log ("set_var: invalid boolean value: %s", val);
  206.             return -1;
  207.             }
  208.         }
  209.         set_bool_var (&Vars[i], n);
  210.         }
  211.         else if (Vars[i].type == VAR_TYPE_LIST)
  212.         set_list_var (&Vars[i], val);
  213.         else
  214.         {
  215.         ASSERT (0);
  216.         }
  217.         return 0;
  218.     }
  219.     }
  220.     log ("set_var(): unknown variable %s", var);
  221.     return -1;
  222. }
  223.  
  224. static char *
  225. get_str_var (char *name)
  226. {
  227.     int     ac;
  228.  
  229.     for (ac = 0; ac < Vars_Size; ac++)
  230.     {
  231.     if (!strcasecmp (name, Vars[ac].name)
  232.         && Vars[ac].type == VAR_TYPE_STR)
  233.         return *(char **) Vars[ac].val;
  234.     }
  235.     return NULL;
  236. }
  237.  
  238. int
  239. config (int init)
  240. {
  241.     FILE   *f;
  242.     char   *ptr, *var, *val;
  243.     int     line = 0;
  244.     char    path[_POSIX_PATH_MAX];
  245.  
  246.     snprintf (path, sizeof (path), "%s/config", Config_Dir);
  247.  
  248.     if ((f = fopen (path, "r")))
  249.     {
  250.     log ("config: reading %s", path);
  251.     while (fgets (Buf, sizeof (Buf), f))
  252.     {
  253.         line++;
  254.         ptr = Buf;
  255.         var = next_arg (&ptr);
  256.         if (!var || *var == '#')
  257.         continue;
  258.         val = next_arg (&ptr);
  259.         if (!val)
  260.         {
  261.         log("config: error in %s:%d: missing value", path, line);
  262.         continue;
  263.         }
  264.         if (set_var (var, val, init) != 0)
  265.         log ("config: error in %s, line %d", path, line);
  266.     }
  267.     fclose (f);
  268.     }
  269.     else if (errno != ENOENT)
  270.     {
  271.     logerr ("config", path);
  272.     return -1;
  273.     }
  274.     if (init)
  275.     config_user_level (get_str_var ("usermode"));
  276.     return 0;
  277. }
  278.  
  279. static void
  280. query_var (CONNECTION * con, struct config *v)
  281. {
  282.     if (v->type == VAR_TYPE_INT)
  283.     send_cmd (con, MSG_SERVER_NOSUCH, "%s = %d", v->name,
  284.           *(int *) v->val);
  285.     else if (v->type == VAR_TYPE_BOOL)
  286.     {
  287.     send_cmd (con, MSG_SERVER_NOSUCH, "%s = %s", v->name,
  288.           (Server_Flags & v->val) ? "on" : "off");
  289.     }
  290.     else if (v->type == VAR_TYPE_LIST)
  291.     {
  292.     char    buf[1024];
  293.     LIST   *tmpList = 0;
  294.  
  295.     buf[0] = 0;
  296.     for (tmpList = *(LIST **) v->val; tmpList; tmpList = tmpList->next)
  297.         snprintf (buf + strlen (buf), sizeof (buf) - strlen (buf),
  298.               "%s ", (char *) tmpList->data);
  299.     send_cmd (con, MSG_SERVER_NOSUCH, "%s = %s", v->name, buf);
  300.     }
  301.     else
  302.     {
  303.     ASSERT (v->type == VAR_TYPE_STR);
  304.     send_cmd (con, MSG_SERVER_NOSUCH, "%s = %s", v->name,
  305.           *(char **) v->val);
  306.     }
  307. }
  308.  
  309. /* 810 [ <var> [ <value> ] ] */
  310. HANDLER (server_config)
  311. {
  312.     char   *av[2];
  313.     int     ac;
  314.  
  315.     (void) tag;
  316.     (void) len;
  317.     ASSERT (validate_connection (con));
  318.     /* only local users should be able to config the server.  this is still
  319.      * problematic as currently user levels are shared across all servers
  320.      * meaning an Elite from another server could still log in and alter the
  321.      * settings.
  322.      */
  323.     CHECK_USER_CLASS ("server_config");
  324.  
  325.     /* allow mods+ to query the config values, only elites can set them */
  326.     if (con->user->level < LEVEL_MODERATOR)
  327.     {
  328.     permission_denied (con);
  329.     return;
  330.     }
  331.  
  332.     ac = split_line (av, FIELDS (av), pkt);
  333.     if (ac == 0)
  334.     {
  335.     /* user requests all config variables */
  336.     for (ac = 0; ac < Vars_Size; ac++)
  337.         query_var (con, &Vars[ac]);
  338.     }
  339.     else if (ac == 1)
  340.     {
  341.     /* user requests the value of a specific variable */
  342.     for (ac = 0; ac < Vars_Size; ac++)
  343.         if (!strcasecmp (av[0], Vars[ac].name))
  344.         {
  345.         query_var (con, &Vars[ac]);
  346.         return;
  347.         }
  348.     send_cmd (con, MSG_SERVER_NOSUCH, "no such variable %s", pkt);
  349.     }
  350.     else
  351.     {
  352.     if (con->user->level < LEVEL_ELITE)
  353.     {
  354.         permission_denied (con);
  355.         return;
  356.     }
  357.     /* user changes the value of a specific variable */
  358.     if (set_var (av[0], av[1], 0) != 0)
  359.     {
  360.         send_cmd (con, MSG_SERVER_NOSUCH, "error setting variable %s",
  361.               av[0]);
  362.     }
  363.     else
  364.         notify_mods (CHANGELOG_MODE, "%s set %s to %s",
  365.              con->user->nick, av[0], av[1]);
  366.     }
  367. }
  368.  
  369. void
  370. free_config (void)
  371. {
  372.     int     i;
  373.  
  374.     for (i = 0; i < Vars_Size; i++)
  375.     if (Vars[i].type == VAR_TYPE_STR && *(char **) Vars[i].val)
  376.         FREE (*(char **) Vars[i].val);
  377.     else if (Vars[i].type == VAR_TYPE_LIST)
  378.         list_free (*(LIST **) Vars[i].val, free_pointer);
  379. }
  380.  
  381. /* load the default settings of the server */
  382. void
  383. config_defaults (void)
  384. {
  385.     int     i;
  386.  
  387.     for (i = 0; i < Vars_Size; i++)
  388.     {
  389.     if (Vars[i].def)
  390.     {
  391.         if (Vars[i].type == VAR_TYPE_STR)
  392.         set_str_var (&Vars[i], (char *) Vars[i].def);
  393.         else if (Vars[i].type == VAR_TYPE_INT)
  394.         set_int_var (&Vars[i], Vars[i].def);
  395.         else if (Vars[i].type == VAR_TYPE_LIST)
  396.         set_list_var (&Vars[i], (char *) Vars[i].def);
  397.         else if (Vars[i].type == VAR_TYPE_BOOL)
  398.         set_bool_var (&Vars[i], Vars[i].def);
  399. #if DEBUG
  400.         else
  401.         ASSERT (0);
  402. #endif
  403.     }
  404.     }
  405. }
  406.  
  407. /* 800 [ :<user> ] <var>
  408.    reset `var' to its default value */
  409. HANDLER (server_reconfig)
  410. {
  411.     int     i;
  412.  
  413.     (void) tag;
  414.     (void) len;
  415.     ASSERT (validate_connection (con));
  416.     CHECK_USER_CLASS ("server_reconfig");
  417.     ASSERT (validate_user (con->user));
  418.     if (con->user->level < LEVEL_ELITE)
  419.     {
  420.     permission_denied (con);
  421.     return;
  422.     }
  423.     for (i = 0; i < Vars_Size; i++)
  424.     if (!strcmp (pkt, Vars[i].name))
  425.     {
  426.         if (!(Vars[i].flags & CF_ONCE))
  427.         {
  428.         send_cmd (con, MSG_SERVER_NOSUCH,
  429.               "reconfig failed: %s may not be changed",
  430.               Vars[i].name);
  431.         }
  432.         else if (Vars[i].def)
  433.         {
  434.         if (Vars[i].type == VAR_TYPE_STR)
  435.             set_str_var (&Vars[i], (char *) Vars[i].def);
  436.         else if (Vars[i].type == VAR_TYPE_INT)
  437.             set_int_var (&Vars[i], Vars[i].def);
  438.         else if (Vars[i].type == VAR_TYPE_BOOL)
  439.             set_bool_var (&Vars[i], Vars[i].def);
  440.         else if (Vars[i].type == VAR_TYPE_BOOL)
  441.             set_list_var (&Vars[i], (char *) Vars[i].def);
  442.         notify_mods (CHANGELOG_MODE, "%s reset %s",
  443.                  con->user->nick, Vars[i].name);
  444.         }
  445.         else
  446.         {
  447.         send_cmd (con, MSG_SERVER_NOSUCH, "no default value for %s",
  448.               pkt);
  449.         }
  450.         return;
  451.     }
  452.     send_cmd (con, MSG_SERVER_NOSUCH, "no such variable %s", pkt);
  453. }
  454.  
  455. static void
  456. nick_check (server_auth_t * auth, void *unused)
  457. {
  458.     USER   *user;
  459.     USERDB *userdb;
  460.  
  461.     (void) unused;
  462.     if (auth->alias)
  463.     {
  464.     user = hash_lookup (Users, auth->alias);
  465.     if (user)
  466.     {
  467.         kill_user_internal (0, user, Server_Name, 0,
  468.                 "you may not use this nickname");
  469.     }
  470.     /* if the nick is registered, drop it now */
  471.     userdb = hash_lookup (User_Db, auth->alias);
  472.     if (userdb)
  473.     {
  474.         log ("nick_check: nuking account %s", userdb->nick);
  475.         hash_remove (User_Db, userdb->nick);
  476.     }
  477.     }
  478. }
  479.  
  480. /* 10116 [ :user ] [server]
  481.  * reload configuration file
  482.  */
  483. HANDLER (rehash)
  484. {
  485.     USER   *sender;
  486.  
  487.     (void) len;
  488.     if (pop_user (con, &pkt, &sender))
  489.     return;
  490.     if (sender->level < LEVEL_ELITE)
  491.     {
  492.     permission_denied (con);
  493.     return;
  494.     }
  495.     notify_mods (SERVERLOG_MODE, "%s reloaded configuration on %s",
  496.          sender->nick, pkt && *pkt ? pkt : Server_Name);
  497.     if (!pkt || !*pkt || !strcasecmp (Server_Name, pkt))
  498.     {
  499.     config (0);
  500.     /* since the motd is stored in memory, reread it */
  501.     motd_close ();
  502.     motd_init ();
  503. #ifndef ROUTING_ONLY
  504.     /* reread filter file */
  505.     load_filter ();
  506.     load_block ();
  507. #endif
  508.     load_server_auth ();
  509.  
  510.     /* since the servers file may have changed, ensure that there is
  511.      * no nickname that matches an alias for a server.
  512.      */
  513.     list_foreach (Server_Auth, (list_callback_t) nick_check, 0);
  514.     }
  515.     /* pass the message even if this is the server we are reloading so that
  516.      * everyone sees the message
  517.      */
  518.     pass_message_args (con, tag, ":%s %s", sender->nick,
  519.                pkt && *pkt ? pkt : Server_Name);
  520. }
  521.